/**
    ******************************************************************************
    * @file    board.c
    * @author  yangFei
    * @brief   pwm adc timer gpio uart相关的配置和控制
    *
    * @version V1.0.0
    * @date    2023.08.10
    * @verbatim
    *
    * @endverbatim
    ******************************************************************************
    * @note
    * @attention
    *
    * Change Logs:
    * Date           Author       Version    Notes
    * 2023.08.10     yangFei      1.0.0      init
    *
    ******************************************************************************
    */
#include "board.h"


#define UART0_RX_LEN  16

static  uint16_t  adc_result[2];

static uint8_t uart0_rx_data[UART0_RX_LEN] = {0x00}, uart0_rx_flag = 0, uart0_rx_pos = 0;

#define US_CORR(us) (us)*50/52    //us延时校正


/**
* @brief  系统各外设时钟初始化
*
* @param  void
*
* @retval void
* @author yangFei
* @date   20230811
* @note   使用内部24M高速时钟
*/
void sys_clk_int(void)
{
    stc_clk_config_t stcClkCfg;
    stcClkCfg.enClkSrc  = ClkRCH;
    stcClkCfg.enHClkDiv = ClkDiv1;
    stcClkCfg.enPClkDiv = ClkDiv1;

    Clk_SetRCHFreq(ClkFreq24Mhz);
    Clk_Init(&stcClkCfg);


    Clk_SetPeripheralGate(ClkPeripheralGpio, TRUE); //GPIO端口外设时钟使能
    Clk_SetPeripheralGate(ClkPeripheralBt, TRUE);  //BT外设时钟使能
    Clk_SetPeripheralGate(ClkPeripheralUart0, TRUE);//串口0外设时钟使能
}

/**
* @brief  引脚初始化
*
* @param  void
*
* @retval void
* @author yangFei
* @date   20230811
* @note
*/
void gpio_int(void)
{
    Gpio_InitIOExt(1, 4, GpioDirOut, TRUE, FALSE, TRUE, FALSE);
    Gpio_InitIOExt(1, 5, GpioDirOut, TRUE, FALSE, TRUE, FALSE);
    Gpio_SetIO(1, 4, FALSE);
    Gpio_SetIO(1, 5, FALSE);
}


/**
* @brief  串口接收中断初始化
*
* @param  void
*
* @retval void
* @author yangFei
* @date   20230814
* @note
*/
void RxIntCallback(void)
{
    uart0_rx_data[uart0_rx_pos++] = Uart_ReceiveData(UARTCH0);
    uart0_rx_pos = uart0_rx_pos % UART0_RX_LEN;
    uart0_rx_flag = 1;
}


/**
* @brief  串口0初始化
*
* @param  void
*
* @retval void
* @author yangFei
* @date   20230814
* @note
*/
void Uart0_TxRx_Init(uint32_t baud, func_ptr_t rxCallback)
{
    uint16_t timer = 0;
    uint32_t pclk;
    stc_uart_irq_cb_t stcUartIrqCb;

    stc_uart_config_t  stcConfig;
    stc_uart_multimode_t stcMulti;
    stc_uart_baud_config_t stcBaud;
    stc_bt_config_t stcBtConfig;

    DDL_ZERO_STRUCT(stcUartIrqCb);
    DDL_ZERO_STRUCT(stcMulti);
    DDL_ZERO_STRUCT(stcBaud);
    DDL_ZERO_STRUCT(stcBtConfig);


    Gpio_InitIOExt(3, 5, GpioDirOut, TRUE, FALSE, FALSE, FALSE);
    Gpio_InitIOExt(3, 6, GpioDirOut, TRUE, FALSE, FALSE, FALSE);

    //通道端口配置
    Gpio_SetFunc_UART0TX_P35();
    Gpio_SetFunc_UART0RX_P36();

    //外设时钟使能
    Clk_SetPeripheralGate(ClkPeripheralBt, TRUE); //模式0/2可以不使能
    Clk_SetPeripheralGate(ClkPeripheralUart0, TRUE);

    stcUartIrqCb.pfnRxIrqCb = rxCallback;
    stcUartIrqCb.pfnTxIrqCb = NULL;
    stcUartIrqCb.pfnRxErrIrqCb = NULL;
    stcConfig.pstcIrqCb = &stcUartIrqCb;
    stcConfig.bTouchNvic = TRUE;


    stcConfig.enRunMode = UartMode1;//测试项，更改此处来转换4种模式测试


    stcMulti.enMulti_mode = UartNormal;//测试项，更改此处来转换多主机模式，mode2/3才有多主机模式

    stcConfig.pstcMultiMode = &stcMulti;

    stcBaud.bDbaud = 0u;//双倍波特率功能
    stcBaud.u32Baud = baud;//更新波特率位置
    stcBaud.u8Mode = UartMode1; //计算波特率需要模式参数
    pclk = Clk_GetPClkFreq();
    timer = Uart_SetBaudRate(UARTCH0, pclk, &stcBaud);

    stcBtConfig.enMD = BtMode2;
    stcBtConfig.enCT = BtTimer;
    Bt_Init(TIM0, &stcBtConfig);//调用basetimer1设置函数产生波特率
    Bt_ARRSet(TIM0, timer);
    Bt_Cnt16Set(TIM0, timer);
    Bt_Run(TIM0);

    Uart_Init(UARTCH0, &stcConfig);
    Uart_EnableIrq(UARTCH0, UartRxIrq);
    Uart_ClrStatus(UARTCH0, UartRxFull);
    Uart_EnableFunc(UARTCH0, UartRx);
}


/**
    * @brief  获取串口0接收的内容
    *
    * @param  uart0_data：串口0结果指针; uart0_data_len：读取的长度
    *
    * @retval 1：有数据更新；0：无数据更新
    * @author yangFei
    * @date   20230814
    * @note   使用单字符队列+延时的方式；uart0_data_len不能超过最大长度
    */
uint8_t get_uart0_data(uint8_t *uart0_data, uint8_t uart0_data_len)
{
    if (uart0_rx_flag == 0 || uart0_data_len > 16)
    {
        return 0;
    }
    else
    {

        delay1ms(UART0_RX_LEN);//等待帧接收完成
        memcpy(uart0_data, uart0_rx_data, uart0_data_len);

        //清空队列和标志位
        memset(uart0_rx_data, 0, sizeof(uart0_rx_data));
        uart0_rx_pos = 0;
        uart0_rx_flag = 0;

        return 1;
    }
}


/**
* @brief  BT1中断服务函数
*
* @param  void
*
* @retval void
* @author yangFei
* @date   20230811
* @note   脉宽的产生使用的是非阻塞式的，延时需要校准
*/
void Bt1Int(void)
{
    if (TRUE == Bt_GetIntFlag(TIM1))
    {
        Gpio_SetIO(1, 4, TRUE);
        Gpio_SetIO(1, 5, FALSE);
        delay1us(US_CORR(500));
        Gpio_SetIO(1, 4, FALSE);
        Gpio_SetIO(1, 5, TRUE);
        delay1us(US_CORR(500));
        Gpio_SetIO(1, 5, FALSE);

        Bt_ClearIntFlag(TIM1);
    }
}


/**
* @brief  定时周期设置 （重载模式）
*
* @param  period：定时器周期，单位微秒
*
* @retval en_result_t
* @author yangFei
* @date   20230811
* @note   小周期使用高速CLK；大周期使用低速CLK；
*/
en_result_t timer_period_set(uint32_t period) //us
{
    stc_bt_config_t   stcConfig;
    en_result_t       enResult = Error;
    uint16_t          timer_period = 0;

    if (period < 80000) //80ms以下使用32分频，误差1.33us 范围2ms-80ms
    {
        timer_period = period * 0.75;
        stcConfig.enPRS   = BtPCLKDiv32;
    }
    else if (period < 600000) //80ms以上使用256分频，误差10us 范围80ms-500ms
    {
        timer_period = period * 0.0937;
        stcConfig.enPRS   = BtPCLKDiv256;
    }
    else
    {
        return Error;
    }

    uint16_t          u16ArrData = 0xffff - timer_period;  //0xe000 - 5400us 0xf000 - 2723us 0x8000 - 21000us  0x2000 - 38000us 0x1000 - 40000us  0 - 43600us    -->1.5个值1us
    uint16_t          u16InitCntData = 0x0000;


    stcConfig.pfnTim1Cb = Bt1Int;

    stcConfig.enGateP = BtPositive;
    stcConfig.enGate  = BtGateDisable;
    //stcConfig.enPRS   = BtPCLKDiv32;
    stcConfig.enTog   = BtTogDisable;
    stcConfig.enCT    = BtTimer;
    stcConfig.enMD    = BtMode2;
    //Bt初始化
    if (Ok != Bt_Init(TIM1, &stcConfig))
    {
        enResult = Error;
    }

    //TIM1中断使能
    Bt_ClearIntFlag(TIM1);
    Bt_EnableIrq(TIM1);
    EnableNvic(TIM1_IRQn, 3, TRUE);

    //设置重载值和计数值，启动计数
    Bt_ARRSet(TIM1, u16ArrData);
    Bt_Cnt16Set(TIM1, u16InitCntData);
    Bt_Run(TIM1);

    return enResult;
}



/**
* @brief  Pca中断服务程序
*
* @param  void
*
* @retval void
* @author yangFei
* @date   20230811
* @note
*/
void PcaInt(void)
{
    if (TRUE == Pca_GetCntIntFlag())
    {
        Pca_ClearCntIntFlag();
    }
    if (TRUE == Pca_GetIntFlag(Module0))
    {
        Pca_ClearIntFlag(Module0);
    }
    if (TRUE == Pca_GetIntFlag(Module1))
    {
        Pca_ClearIntFlag(Module1);
    }
    if (TRUE == Pca_GetIntFlag(Module2))
    {
        Pca_ClearIntFlag(Module2);
    }
    if (TRUE == Pca_GetIntFlag(Module3))
    {
        Pca_ClearIntFlag(Module3);
    }
    if (TRUE == Pca_GetIntFlag(Module4))
    {
        Pca_ClearIntFlag(Module4);
    }
}


/**
* @brief  PCA PWM功能初始化
*
* @param  void
*
* @retval void
* @author yangFei
* @date   20230811
* @note   使用的引脚是P23；
*         8位分辨率；通过修改分频改频率；内部24M晶振情况下默认2分频最高频率大概47K；
 *         初始化后调用Pca_Run();启动；调用Pca_CapDataHSet修改占空比；
*/
en_result_t pca_pwm_init(void)
{
    stc_pca_config_t stcConfig;
    stc_pca_capmodconfig_t stcModConfig;
    en_result_t      enResult = Ok;
    uint8_t          u8CcaplData = 0x20;
    uint8_t          u8CcaphData = 0x80;  //0-255


    Clk_SetPeripheralGate(ClkPeripheralPca, TRUE);//PCA外设时钟开启

    Gpio_SetFunc_PCA_CH0_P23(0);

    stcConfig.enCIDL = IdleGoon;
    stcConfig.enWDTE = PCAWDTDisable;
    stcConfig.enCPS  = PCAPCLKDiv2; //32 340-255us   16 170-127us  2 47k-21us

    stcConfig.pfnPcaCb = PcaInt;

    stcModConfig.enECOM = ECOMEnable;
    stcModConfig.enCAPP = CAPPDisable;
    stcModConfig.enCAPN = CAPNDisable;
    stcModConfig.enMAT  = MATDisable;
    stcModConfig.enTOG  = TOGDisable;
    stcModConfig.enPWM  = PCAPWMEnable;


    if (Ok != Pca_Init(&stcConfig))
    {
        enResult = Error;
    }
    if (Ok != Pca_CapModConfig(Module0, &stcModConfig))
    {
        enResult = Error;
    }

    Pca_CapDataLSet(Module0, u8CcaplData);
    Pca_CapDataHSet(Module0, u8CcaphData);



    return enResult;
}



/**
    * @brief  ADC转换中断回调函数
    *
    * @param  void
    *
    * @retval void
    * @author yangFei
    * @date   20230811
    * @note   中断标志位判断和清零，已在库函数中处理Adc_IRQHandler();
    */
void AdcContIrqCallback(void)
{

    for (uint8_t u8Channel = 0; u8Channel < 2; u8Channel++)
    {
        Adc_GetScanResult(u8Channel, &adc_result[u8Channel]);
    }
}

/**
    * @brief  ADC区间中断回调函数
    *
    * @param  void
    *
    * @retval void
    * @author yangFei
    * @date   20230811
    * @note   占位
    */
void AdcRegIrqCallback(void)
{
    // Adc_ClrRegIrqState();
}

/**
    * @brief  ADC上超出区间中断回调函数
    *
    * @param  void
    *
    * @retval void
    * @author yangFei
    * @date   20230811
    * @note   占位
    */
void AdcHhtIrqCallback(void)
{
    // Adc_ClrHhtIrqState();
}

/**
    * @brief  ADC下超出区间中断回调函数
    *
    * @param  void
    *
    * @retval void
    * @author yangFei
    * @date   20230811
    * @note   占位
    */
void AdcLltIrqCallback(void)
{
    // Adc_ClrLltIrqState();
}

/**
    * @brief  ADC初始化
    *
    * @param  void
    *
    * @retval en_result_t
    * @author yangFei
    * @date   20230811
    * @note   引脚P24-0通道 P26-1通道；目前使用的方式是多通道中断扫描
    */
en_result_t adc_init()
{
    stc_adc_cfg_t             stcAdcCfg;
    stc_adc_scan_cfg_t        stcAdcScanCfg;
    stc_adc_irq_t             stcAdcIrq;
    stc_adc_irq_calbakfn_pt_t stcAdcIrqCalbaks;

    DDL_ZERO_STRUCT(stcAdcCfg);
    DDL_ZERO_STRUCT(stcAdcScanCfg);
    DDL_ZERO_STRUCT(stcAdcIrq);
    DDL_ZERO_STRUCT(stcAdcIrqCalbaks);



    if (Ok != Clk_SetPeripheralGate(ClkPeripheralAdcBgr, TRUE))  //ADCBGR 外设时钟使能
    {
        return Error;
    }

    //adc gpio config
    Gpio_SetAnalog(2, 4, TRUE);
    Gpio_SetAnalog(2, 6, TRUE);


    Adc_Enable();
    M0P_BGR->CR_f.BGR_EN = 0x1u;   //BGR必须使能
    M0P_BGR->CR_f.TS_EN = 0x0u;    //内置温度传感器，视使用需求
    delay100us(1);

    stcAdcCfg.enAdcOpMode = AdcScanMode;               //扫描采样模式
    stcAdcCfg.enAdcClkSel = AdcClkSysTDiv1;            //PCLK
    stcAdcCfg.enAdcSampTimeSel = AdcSampTime8Clk;      //8个采样时钟
    //stcAdcCfg.enAdcRefVolSel = RefVolSelInBgr2p5;    //参考电压:内部2.5V(avdd>3V,SPS<=200kHz)
    stcAdcCfg.enAdcRefVolSel = RefVolSelAVDD;          //参考电压:AVDD
    stcAdcCfg.bAdcInBufEn = FALSE;                     //电压跟随器如果使能，SPS采样速率 <=200K
    stcAdcCfg.enAdcTrig0Sel = AdcTrigDisable;          //ADC转换自动触发设置
    stcAdcCfg.enAdcTrig1Sel = AdcTrigDisable;
    Adc_Init(&stcAdcCfg);

    stcAdcIrq.bAdcIrq = TRUE;                            //转换完成中断函数入口配置使能
    stcAdcIrq.bAdcRegCmp = FALSE;
    stcAdcIrq.bAdcHhtCmp = FALSE;
    stcAdcIrq.bAdcLltCmp = FALSE;
    stcAdcIrqCalbaks.pfnAdcContIrq = AdcContIrqCallback; //转换完成中断入口函数
    stcAdcIrqCalbaks.pfnAdcRegIrq = AdcRegIrqCallback;
    stcAdcIrqCalbaks.pfnAdcHhtIrq = AdcHhtIrqCallback;
    stcAdcIrqCalbaks.pfnAdcLltIrq = AdcLltIrqCallback;
    Adc_ConfigIrq(&stcAdcIrq, &stcAdcIrqCalbaks);        //转换中断入口函数配置
    Adc_EnableIrq();                                     //中断使能
    Adc_CmpCfg(&stcAdcIrq);                              //结果比较中断使能/禁止配置

    stcAdcScanCfg.u8AdcScanModeCh = ADC_SCAN_CH0_EN
                                    | ADC_SCAN_CH1_EN;

    stcAdcScanCfg.u8AdcSampCnt = 0x1;                   //连续扫描转换次数，保持通道的倍数，6通道 = 0x5+1(1倍)，或者11+1(2倍)……
    Adc_ConfigScanMode(&stcAdcCfg, &stcAdcScanCfg);

    return Ok;
}

/**
    * @brief  获取ADC的采样值
    *
    * @param  adc_data：ADC结果指针
    *
    * @retval en_result_t
    * @author yangFei
    * @date   20230811
    * @note   内部未进行换算，12位adc（3.3V-4096）
    */
en_result_t get_adc(uint16_t *adc_data)
{
    Adc_Start();

    delay100us(1);

    memcpy(adc_data, adc_result, sizeof(adc_result));

    return Ok;
}




/************************ (C) COPYRIGHT LEADINNO *****END OF FILE****/

